/**
 * 数据库同步工具
 * 
 * 用于从数据库自动同步表结构信息
 * 支持增量同步，只处理有变化的表结构
 * 
 * @module dbSync
 */

import fs from 'fs';
import path from 'path';
import minimist from 'minimist';
import { fileURLToPath } from 'url';
import { apiLogger } from './apiLogger.js';
import { getConfig } from './configAdapter.js';
import ApiTester from './apiTester.js';

// 获取当前文件目录
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// 解析命令行参数
const args = minimist(process.argv.slice(2), {
    boolean: ['force', 'verbose', 'dry-run'],
    string: ['tables', 'output', 'schema'],
    alias: {
        f: 'force',     // 强制同步所有表
        v: 'verbose',   // 详细输出
        t: 'tables',    // 指定要同步的表
        o: 'output',    // 指定输出目录
        s: 'schema',    // 指定数据库schema
        d: 'dry-run'    // 干运行模式
    },
    default: {
        force: false,
        verbose: false,
        'dry-run': false
    }
});

// 加载配置
const config = getConfig();
const RAW_DATA_DIR = path.resolve(config.OUTPUT_BASE_DIR || '../', config.RAW_DATA_DIR || 'raw-data');
const SCHEMA_NAME = args.schema || config.SCHEMA_NAME;
const VERBOSE = args.verbose;
const FORCE_SYNC = args.force;
const DRY_RUN = args['dry-run'];

// 记录器
const logger = {
    log: (message) => {
        console.log(`[INFO] ${message}`);
    },
    info: (message) => {
        console.log(`[INFO] ${message}`);
    },
    warn: (message) => {
        console.warn(`[WARN] ${message}`);
    },
    error: (message, error) => {
        console.error(`[ERROR] ${message}`, error || '');
    },
    verbose: (message) => {
        if (VERBOSE) {
            console.log(`[VERBOSE] ${message}`);
        }
    }
};

/**
 * 获取表名列表
 * 
 * @param {string[]} requestedTables - 请求同步的表名
 * @returns {Promise<string[]>} 表名列表
 */
async function getTableList(requestedTables) {
    try {
        const tester = new ApiTester(config);

        // 测试连接
        await tester.testConnection();

        // 获取认证令牌
        const authResult = await tester.testAuthentication();
        if (!authResult.success) {
            throw new Error('API认证失败');
        }

        // 获取表列表
        const tablesResult = await tester.testGetTables();
        if (!tablesResult.success) {
            throw new Error('获取表列表失败');
        }

        // 过滤表名
        let tables = tablesResult.tables || [];

        // 如果指定了表名，则只处理这些表
        if (requestedTables && requestedTables.length > 0) {
            tables = tables.filter(table => requestedTables.includes(table));
        }

        return tables;
    } catch (error) {
        logger.error('获取表列表失败', error);
        return [];
    }
}

/**
 * 检查表是否有变化
 * 
 * @param {string} tableName - 表名
 * @param {Object} tableData - 新的表结构数据
 * @returns {boolean} 是否有变化
 */
function hasTableChanged(tableName, tableData) {
    try {
        // 如果强制同步，则总是返回true
        if (FORCE_SYNC) {
            return true;
        }

        // 尝试读取现有数据
        const tablePath = path.join(RAW_DATA_DIR, tableName);
        const columnsPath = path.join(tablePath, 'columns.json');

        if (!fs.existsSync(columnsPath)) {
            logger.verbose(`表${tableName}没有现有数据，需要同步`);
            return true;
        }

        // 读取现有数据
        const existingData = JSON.parse(fs.readFileSync(columnsPath, 'utf8'));

        // 简单比较结构体
        const existingHash = JSON.stringify(existingData);
        const newHash = JSON.stringify(tableData);

        const changed = existingHash !== newHash;
        if (changed) {
            logger.verbose(`表${tableName}有变化，需要同步`);
        } else {
            logger.verbose(`表${tableName}没有变化，跳过同步`);
        }

        return changed;
    } catch (error) {
        logger.error(`检查表${tableName}变化时出错`, error);
        // 出错时保守处理，认为有变化
        return true;
    }
}

/**
 * 保存表结构数据
 * 
 * @param {string} tableName - 表名
 * @param {Object} data - 表结构数据
 * @param {string} dataType - 数据类型
 * @returns {boolean} 是否保存成功
 */
function saveTableData(tableName, data, dataType) {
    try {
        // 干运行模式下不实际保存
        if (DRY_RUN) {
            logger.info(`[干运行] 将保存${tableName}的${dataType}数据`);
            return true;
        }

        const tableDir = path.join(RAW_DATA_DIR, tableName);
        if (!fs.existsSync(tableDir)) {
            fs.mkdirSync(tableDir, { recursive: true });
        }

        const filePath = path.join(tableDir, `${dataType}.json`);
        fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');

        logger.verbose(`保存${tableName}的${dataType}数据到${filePath}`);
        return true;
    } catch (error) {
        logger.error(`保存${tableName}的${dataType}数据失败`, error);
        return false;
    }
}

/**
 * 同步表结构数据
 * 
 * @param {string} tableName - 表名
 * @returns {Promise<boolean>} 是否同步成功
 */
async function syncTableStructure(tableName) {
    try {
        logger.info(`开始同步表${tableName}...`);

        // 这里应使用实际的API获取表结构数据
        // 目前我们仅创建一个示例数据
        const columnsData = {
            tableName,
            columns: [
                {
                    columnName: 'id',
                    dataType: 'int',
                    isNullable: 'NO',
                    columnDefault: null,
                    isPrimaryKey: 'YES',
                    columnComment: '主键ID'
                },
                {
                    columnName: 'name',
                    dataType: 'varchar',
                    isNullable: 'NO',
                    columnDefault: null,
                    isPrimaryKey: 'NO',
                    columnComment: '名称'
                },
                {
                    columnName: 'created_at',
                    dataType: 'timestamp',
                    isNullable: 'NO',
                    columnDefault: 'CURRENT_TIMESTAMP',
                    isPrimaryKey: 'NO',
                    columnComment: '创建时间'
                }
            ],
            tableComment: `${tableName}表`,
            createdAt: new Date().toISOString()
        };

        // 检查表是否有变化
        if (!hasTableChanged(tableName, columnsData)) {
            logger.info(`表${tableName}没有变化，跳过`);
            return true;
        }

        // 保存列数据
        const saveColumnsResult = saveTableData(tableName, columnsData, 'columns');
        if (!saveColumnsResult) {
            return false;
        }

        // 保存索引数据
        const indexesData = {
            tableName,
            indexes: [
                {
                    indexName: 'PRIMARY',
                    columnName: 'id',
                    isUnique: 'YES',
                    indexType: 'BTREE'
                },
                {
                    indexName: 'idx_name',
                    columnName: 'name',
                    isUnique: 'NO',
                    indexType: 'BTREE'
                }
            ],
            createdAt: new Date().toISOString()
        };

        const saveIndexesResult = saveTableData(tableName, indexesData, 'indexes');
        if (!saveIndexesResult) {
            return false;
        }

        // 保存外键数据
        const foreignKeysData = {
            tableName,
            foreignKeys: [],
            createdAt: new Date().toISOString()
        };

        const saveForeignKeysResult = saveTableData(tableName, foreignKeysData, 'foreignKeys');
        if (!saveForeignKeysResult) {
            return false;
        }

        logger.info(`表${tableName}同步成功`);
        return true;
    } catch (error) {
        logger.error(`同步表${tableName}结构失败`, error);
        return false;
    }
}

/**
 * 运行同步过程
 */
async function run() {
    try {
        // 确保输出目录存在
        if (!fs.existsSync(RAW_DATA_DIR) && !DRY_RUN) {
            fs.mkdirSync(RAW_DATA_DIR, { recursive: true });
        }

        // 解析指定要同步的表参数
        const requestedTables = args.tables ? args.tables.split(',') : [];

        logger.info('开始数据库同步...');
        logger.info(`数据库Schema: ${SCHEMA_NAME}`);
        logger.info(`强制同步: ${FORCE_SYNC ? '是' : '否'}`);
        logger.info(`指定表: ${requestedTables.length > 0 ? requestedTables.join(', ') : '所有表'}`);
        logger.info(`干运行模式: ${DRY_RUN ? '是' : '否'}`);
        logger.info(`输出目录: ${RAW_DATA_DIR}`);

        // 获取表列表
        const tables = await getTableList(requestedTables);

        if (tables.length === 0) {
            logger.warn('没有找到可同步的表');
            return;
        }

        logger.info(`找到${tables.length}个表准备同步`);

        // 同步每个表
        const results = {
            total: tables.length,
            success: 0,
            skipped: 0,
            failed: 0
        };

        for (const tableName of tables) {
            try {
                const success = await syncTableStructure(tableName);
                if (success) {
                    results.success++;
                } else {
                    results.failed++;
                }
            } catch (error) {
                logger.error(`处理表${tableName}时出错`, error);
                results.failed++;
            }
        }

        // 输出结果
        logger.info('\n同步完成!');
        logger.info(`总计: ${results.total}`);
        logger.info(`成功: ${results.success}`);
        logger.info(`跳过: ${results.skipped}`);
        logger.info(`失败: ${results.failed}`);

        // 更新元数据
        if (!DRY_RUN && results.success > 0) {
            const metadata = {
                lastSync: new Date().toISOString(),
                tables: tables,
                syncResults: results
            };

            const metadataDir = path.join(RAW_DATA_DIR, 'metadata');
            if (!fs.existsSync(metadataDir)) {
                fs.mkdirSync(metadataDir, { recursive: true });
            }

            fs.writeFileSync(
                path.join(metadataDir, 'sync-metadata.json'),
                JSON.stringify(metadata, null, 2),
                'utf8'
            );

            logger.info('已更新同步元数据');
        }
    } catch (error) {
        logger.error('同步过程出错', error);
        process.exit(1);
    }
}

// 执行同步
if (import.meta.url === `file://${process.argv[1]}`) {
    run();
}

export {
    syncTableStructure,
    getTableList,
    hasTableChanged
}; 